﻿using System;
using System.Linq.Expressions;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading.Tasks;

namespace N3P.WCF.Proxyless.FullFramework45
{
    public class WcfClient<T> : Proxyless.WcfClient<T>
    {
        #region Constructors (5)

        /// <summary>
        /// Initializes a new instance of the <see cref="T:N3P.WCF.Proxyless.WcfClient`1" /> class.
        /// </summary>
        /// <param name="endpointConfigurationName">The name of the endpoint in the application configuration file</param>
        /// <param name="remoteAddress">The address of the service</param>
        public WcfClient(string endpointConfigurationName, string remoteAddress)
            : base(endpointConfigurationName, remoteAddress)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:N3P.WCF.Proxyless.WcfClient`1" /> class using the specified target address and endpoint information
        /// </summary>
        /// <param name="endpointConfigurationName">The name of the endpoint in the application configuration file.</param>
        /// <param name="remoteAddress">The address of the service.</param>
        public WcfClient(string endpointConfigurationName, EndpointAddress remoteAddress)
            : base(endpointConfigurationName, remoteAddress)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:N3P.WCF.Proxyless.WcfClient`1" /> class using the specified binding and target address
        /// </summary>
        /// <param name="binding">The binding with which to make calls to the service.</param>
        /// <param name="remoteAddress">The address of the service endpoint.</param>
        public WcfClient(Binding binding, EndpointAddress remoteAddress)
            : base(binding, remoteAddress)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:N3P.WCF.Proxyless.WcfClient`1" /> class using the configuration information specified in the application configuration file by <paramref cref="endpointConfigurationName" />.
        /// </summary>
        /// <param name="endpointConfigurationName"></param>
        public WcfClient(string endpointConfigurationName)
            : base(endpointConfigurationName)
        {
        }

        /// <summary>
        /// Initializes a new instance of the WcfCaller class using the default target endpoint from the application configuration file.
        /// </summary>
        public WcfClient()
        {
        }

        #endregion Constructors 

        /// <summary>
        /// Calls a method without a return on the service
        /// </summary>
        /// <param name="callExpression">The expression that will be used to call the service method</param>
        /// <returns>A task that will complete when the underlying call does</returns>
        public Task CallAsync(Expression<Action<T>> callExpression)
        {
            return Continuation.AsTask(continuation => Call(callExpression, continuation, true));
        }

        /// <summary>
        /// Calls a method with a return on the service
        /// </summary>
        /// <typeparam name="TResult">The type of result the call should have</typeparam>
        /// <param name="callExpression">The expression that will be used to call the service method</param>
        /// <returns>A task containing the result of the call</returns>
        public Task<TResult> CallAsync<TResult>(Expression<Func<T, TResult>> callExpression)
        {
            return Continuation.AsTask<TResult>(continuation => Call(callExpression, continuation, true));          
        }
    }
}
